'''
Created on 23 Jan 2014

@author: georgep
'''
import json as simplejson
import urllib2
from utils import *
import socket
from difflib import Differ

class Squeezebox():
    #===============================================================================
    # Squeezebox - Class for interacting with the Squeezebox server and player
    #===============================================================================
    def __init__(self, host="127.0.0.1", port=9000, player_id=""):
        if host:
            self.host = host
        else:
            self.host = self.discover()
        self.port = port
        self.server_url = "http://%s:%s/jsonrpc.js" % (self.host, self.port)
        self.player_id = player_id        
        
    def query(self, *args):
        # Build query parmeters
        params = simplejson.dumps({'id':1, 'method':'slim.request', 'params':[self.player_id, list(args)]})
        logging.debug(str("Server Query: params: "+ params+ " Server url: "+ self.server_url))
        req = urllib2.Request(self.server_url, params)
        try:
            response = urllib2.urlopen(req, timeout=2)
            response_txt = response.read()
            return simplejson.loads(response_txt)['result']
        except urllib2.URLError, e:
            logging.error("Query failed or timed out!")
    
    
    def connectToServer(self):
        # Try to connect to server defined when the object was initialised
        version = self.getVersion();
        if version:
            logging.debug(str("Connected to Logitech Media Server version "+version['_version']))
        else:
            logging.debug(str("Failed to find server defined when the Squeezebox object was initialised"))
            # Try to discover the server:
            ip = self.discover()
            if ip:
                logging.debug(str("Discovered server on "+ip))
                self.host = ip;
                self.server_url = "http://%s:%s/jsonrpc.js" % (self.host, self.port)
            else:
                logging.debug(str("Failed to discover the server"))
                self.host = None;
                self.server_url = "http://%s:%s/jsonrpc.js" % (self.host, self.port)
        return self.host
                
    def connectToLocalPlayer(self):        
        self.player_id = None
        if self.host:
            logging.debug(str("Looking for local player"))
            nPlayers = self.getPlayerCount()
	    #Read MAC address of local ethernet and wifi. Note added rstrip to remove newline which sometimes occured and messed up comparison with squeezebox plater_id
            eth0_mac = open('/sys/class/net/eth0/address').read().rstrip()
            wlan0_mac = open('/sys/class/net/wlan0/address').read().rstrip()
	    #print(str("eth0="+ eth0_mac + "wlan0="+ wlan0_mac))
            # Try player with eth0 or wlan0 mac address
            for n in range(nPlayers):
                player_id = str(self.getPlayerID(n))
		#print wlan0_mac
                #print player_id
		#print list(Differ().compare(wlan0_mac, player_id))
		#print(str("found player on server: "+ player_id))
                if player_id == wlan0_mac:
		    logging.debug(str("Local player "+ player_id +" found"))
                    self.player_id = player_id
                if player_id.lower() == eth0_mac.lower():
                    logging.debug(str("Local player "+ player_id +" found"))
                    self.player_id = player_id
        else:
            logging.error(str("Cannot look for player, not connected to server"))
        return self.player_id
            
            
                    
                
             
        
        
    
    def discover(self):
        logging.debug("Discovering Sever...")
        from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_REUSEADDR, SO_BROADCAST
        timeout = 2 # seconds
        address = '255.255.255.255' # udp group address
        port = 3483 # Server listens and responds on this UDP port
        soc = socket(AF_INET, SOCK_DGRAM)
        soc.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        soc.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
        soc.settimeout(timeout)
        soc.sendto(b'e', (address, port))
        ip, port = None, None
        
        data = b""
        try:
            data = soc.recvfrom(10)
            if b'E' == data[0]:
                ip, port = data[1]
                #print "IP ",ip, "port ", port
        except:
            pass
        return ip
    
    #========================================================================
    # Get/set methods
    #========================================================================    
    def getVersion(self):
        return self.query("version", "?")
    def getPlayerCount(self):
        return self.query("player", "count", "?")["_count"]
    def getPlayerID(self,playerIndex):
        return self.query("player", "id", playerIndex, "?")["_id"]
    def setVolume(self, volume):
        self.query("mixer", "volume", volume)
    def getVolume(self):
        return self.query( "mixer", "volume", "?")
    #def getMuting(self):
    #    return self.query( "mixer", "muting", "?")
    def getMuting(self):
        #print self.query( "mixer", "muting", "?")['_muting']
        muting = self.query( "mixer", "muting", "?")['_muting']
        if (str(muting) == 'None') or (str(muting) == '0'):
            return False
        else:
            return True    
    def getShuffle(self):
        shuffle = self.query( "playlist", "shuffle", "?")['_shuffle']
        if (str(shuffle) == 'None') or (str(shuffle) == '0'):
            return False
        else:
            return True
    def setMuting(self,mute):
        if mute:
            self.query( "mixer", "muting", "1")
        else:
            self.query( "mixer", "muting", "0")
    def setShuffle(self,shuffle):
        if shuffle:
            self.query( "playlist", "shuffle", "1")
        else:
            self.query( "playlist", "shuffle", "0")
    def nextSong(self):
        return self.query("playlist", "index", "+1")   
    def previousSong(self):
        return self.query("playlist", "index", "-1") 
    def playPause(self):
        return self.query("pause")
    def getArtists(self):
        result = self.query( "artists", 0, 9999)
        if result:
            return result['artists_loop']
    def getAlbums(self):
        return self.query( "albums", 0, 9999)['albums_loop']  
    def getPlaylists(self):
        return self.query( "playlists", 0, 9999)['playlists_loop'] 
    #def getPlaylist(self, playlist_id):
     #   return self.query( "playlisttracks", playlist_id, 0, 9999)['playlisttracks_loop'] 
    def getArtistAlbums(self, artist_id):
        return self.query("albums", 0, 99, "tags:al", "artist_id:"+str(artist_id))['albums_loop']
    def getAlbum(self, album_id):
        try:
            result = self.query("tracks", 0, 99, "tags:al", "sort tracknum", "album_id:"+str(album_id))['titles_loop']
        except:
            #logging.error("Query error. Returning empty result")
            result = []
        return result
    def getPlaylist(self, id):
        result = self.query("playlists", "tracks", 0, 999, "tags:al", "playlist_id:"+str(id))
        # Make sure the playlist isn't empty        
        if result['count']:
            result = result['playlisttracks_loop']  
        else: 
            result = []            
        return result          
        #return self.query("playlists", "tracks", 0, 999, "tags:al", "playlist_id:"+str(id))['playlisttracks_loop']        
    def playAlbum(self, id):
        print "playing album"
        return self.query("playlistcontrol", "cmd:load", "album_id:"+str(id))
    def playPlaylist(self, id):
        return self.query("playlistcontrol", "cmd:load", "playlist_id:"+str(id))
    def playTrack(self, id):
        return self.query("playlistcontrol", "cmd:load", "track_id:"+str(id))
    def getCoverURL(self):
        return 'http://%s:%s/music/current/cover.jpg?player=%s' % (self.host, self.port,self.player_id)
    def getQue(self):        
        result = self.query("status", "playlist_tracks")
        #Make sure the que isn't empty
        print "QUE:::::::", result
        if result['playlist_tracks']:
            result = result['playlist_loop']
        else: 
            result = []
            
        return result
        
        #print self.query("status", "playlist_tracks")
        #return self.query("status", "playlist_tracks")['playlist_loop']
    



    

